package lib

import (
	"GameServer/Common/data"
	"GameServer/Common/utils"
	"GameServer/Game/errors"
	"GameServer/Game/m"
	"fmt"
)

// 给用户添加宠物，用户拥有宠物 IsHave=true，Status=0，状态为0，需要用户戳开蛋，状态才为1。
func AddPet(u *m.User, tid int64) (kv *m.BaseKV, uPropPet *m.UpdatePet, uPropPetInfo *m.UpdatePetInfo, err error) {
	uPet := u.GetUserPet()
	petTpl, ok := data.Get("Pets", uint64(tid))
	if !ok {
		err = errors.NewErrcode(data.Errcode.ConfigNotFound, fmt.Sprintf("没有这个宠物配置tid:%d", tid))
		return
	}
	defer uPet.Update(uPet)
	petT := petTpl.(data.Pet)

	if pet, ok := uPet.Pets[tid]; ok {
		if pet.IsHave {
			err = errors.New("已经有这只宠物")
			return nil, nil, nil, err
		}
		// 升阶
		newStep := pet.Step + 1
		pSkillTpl, ok := data.Foreach(petT.SkillTpl, func(val interface{}) bool {
			val1 := val.(data.PetSkill)
			if int64(val1.Lv) == pet.Lv && int64(val1.Step) == newStep {
				return true
			}
			return false
		})
		if !ok {
			err = errors.NewErrcode(data.Errcode.ConfigNotFound, fmt.Sprintf("没有这个宠物技能模板：%s 配置 lv:%d, step:%d", petT.SkillTpl, pet.Lv, newStep))
			return nil, nil, nil, err
		}

		// 宠物激活
		if pet.Status == 1 {
			kv = &m.BaseKV{Key: data.GlobalEnum.Star, Val: int64(pSkillTpl.(data.PetSkill).Star) - pet.Star}
		}
		pet.Star = int64(pSkillTpl.(data.PetSkill).Star)
		pet.Step = newStep
		pet.SkillVal = pSkillTpl.(data.PetSkill).SkillVal
		pet.IsHave = true
		uPropPet = &m.UpdatePet{
			Tid:         pet.Tid,
			Lv:          pet.Lv,
			Exp:         pet.Exp,
			Step:        pet.Step,
			SkillVal:    int64(pet.SkillVal * 1000), // 浮点型 保留3位小数
			LiveEndTime: pet.LiveEndTime,
		}
		if len(uPet.Pets) == 1 {
			uPet.SelectTid = tid
			uPropPetInfo = &m.UpdatePetInfo{
				ExpNum:    uPet.ExpNum,
				FoodNum:   uPet.FoodNum,
				SelectTid: uPet.SelectTid,
			}
			return kv, uPropPet, uPropPetInfo, nil
		}
		return kv, uPropPet, nil, nil
	}

	// 获得新的宠物
	skillTpl, ok := data.Get(petT.SkillTpl, uint64(1))
	if !ok {
		err = errors.NewErrcode(data.Errcode.ConfigNotFound, fmt.Sprintf("没有这个宠物技能模板：%s 配置tid:%d", petT.SkillTpl, 1))
		return
	}
	skillT := skillTpl.(data.PetSkill)

	pet := &m.Pet{Tid: tid, Lv: 1, Exp: 0, Step: 1, Star: int64(skillT.Star), SkillVal: skillT.SkillVal, IsHave: true}

	// 首次获得
	if len(uPet.Pets) == 0 {
		uPet.SelectTid = tid
		uPropPetInfo = &m.UpdatePetInfo{
			ExpNum:    uPet.ExpNum,
			FoodNum:   uPet.FoodNum,
			SelectTid: uPet.SelectTid,
		}
	}
	uPet.Pets[tid] = pet
	uPropPet = &m.UpdatePet{
		Tid:         pet.Tid,
		Lv:          pet.Lv,
		Exp:         pet.Exp,
		Step:        pet.Step,
		SkillVal:    int64(pet.SkillVal * 1000),
		LiveEndTime: pet.LiveEndTime,
	}
	return
}

// 宠物进阶
func AddPetStep(u *m.User, tid int64, val int64) (uProp *m.UpdateProp, uPropPet *m.UpdatePet, err error) {
	uPet := u.GetUserPet()

	petTpl, ok := data.Get("Pets", uint64(tid))
	if !ok {
		err = errors.NewErrcode(data.Errcode.ConfigNotFound, fmt.Sprintf("没有这个宠物配置tid:%d", tid))
		return
	}
	defer uPet.Update(uPet)
	petT := petTpl.(data.Pet)
	uProp = m.NewUpdateProp()
	if pet, ok := uPet.Pets[tid]; ok {
		// 升阶
		newStep := pet.Step + val
		pSkillTpl, ok := data.Foreach(petT.SkillTpl, func(val interface{}) bool {
			val1 := val.(data.PetSkill)
			if int64(val1.Lv) == pet.Lv && int64(val1.Step) == newStep {
				return true
			}
			return false
		})
		if !ok {
			err = errors.NewErrcode(data.Errcode.ConfigNotFound, fmt.Sprintf("没有这个宠物技能模板：%s 配置 lv:%d, step:%d", petT.SkillTpl, pet.Lv, newStep))
			return nil, nil, err
		}
		skillT := pSkillTpl.(data.PetSkill)
		fmt.Println("宠物升阶加星星:", pet.Tid, "lv:", pet.Lv, "step:", pet.Step, int64(skillT.Star), " : ", pet.Star, " : ", utils.Obj2JsonStr(uProp.Kvs))
		uProp.Kvs = append(uProp.Kvs, &m.BaseKV{Key: data.GlobalEnum.Star, Val: int64(skillT.Star) - pet.Star})

		pet.Star = int64(skillT.Star)
		fmt.Println("宠物升阶加星星 end:", pet.Tid, "lv:", pet.Lv, "step:", pet.Step, int64(skillT.Star), " : ", pet.Star, " : ", utils.Obj2JsonStr(uProp.Kvs))
		pet.Step = newStep
		pet.SkillVal = pSkillTpl.(data.PetSkill).SkillVal
		if !pet.IsHave {
			return uProp, nil, nil
		}

		uPropPet = &m.UpdatePet{
			Tid:         pet.Tid,
			Lv:          pet.Lv,
			Exp:         pet.Exp,
			Step:        pet.Step,
			SkillVal:    int64(pet.SkillVal * 1000),
			LiveEndTime: pet.LiveEndTime,
		}
		return uProp, uPropPet, nil
	}

	//
	skillTpl, ok := data.Get(petT.SkillTpl, uint64(1))
	if !ok {
		err = errors.NewErrcode(data.Errcode.ConfigNotFound, fmt.Sprintf("没有这个宠物技能模板：%s 配置tid:%d", petT.SkillTpl, 1))
		return
	}
	skillT := skillTpl.(data.PetSkill)
	uProp.Kvs = append(uProp.Kvs, &m.BaseKV{Key: data.GlobalEnum.Star, Val: int64(skillT.Star)})
	pet := &m.Pet{Tid: tid, Lv: 1, Exp: 0, Star: int64(skillT.Star), Step: val, SkillVal: skillT.SkillVal, IsHave: false}
	uPet.Pets[tid] = pet
	return
}

// 激活宠物
func ActivePet(u *m.User, tid int64) (uProp *m.UpdateProp, err error) {
	uPet := u.GetUserPet()
	if pet, ok := uPet.Pets[tid]; ok {
		if pet.Status == 1 {
			return nil, nil
		}
		defer uPet.Update(uPet)
		uProp = m.NewUpdateProp()
		uProp.Kvs = append(uProp.Kvs, &m.BaseKV{Key: data.GlobalEnum.Star, Val: pet.Star})
		pet.Status = 1
		return
	}
	err = errors.NewErrcode(data.Errcode.NotFound, fmt.Sprintf("没有这个宠物：%d", tid))
	return
}

// 宠物吃饲料
func PetEatFood(us *m.User, petTid int64, num int64) (uProp *m.UpdateProp, uPet *m.UserPet, pet *m.Pet, addExp int64, err error) {
	uPet = us.GetUserPet()
	// 玩家拥有的食物不够吃
	if uPet.FoodNum < num {
		err = errors.NewErrcode(data.Errcode.NoPetFood, fmt.Sprintf("玩家的饲料不够吃，玩家饲料%d，吃饲料%d", uPet.FoodNum, num))
		return
	}
	pet, err = uPet.GetPet(petTid)
	if err != nil {
		return
	}
	// 获取一袋饲料包含经验药水
	tpl, ok := data.Get("PetAddInfos", uint64(1))
	if !ok {
		err = errors.NewErrcode(data.Errcode.ConfigNotFound, fmt.Sprintf("没有PetAddInfos配置表，或的数据长度小于2"))
		return
	}
	expT := tpl.(data.PetAddInfo) // 一袋饲料的经验
	tpl, ok = data.Get("PetAddInfos", uint64(2))
	if !ok {
		err = errors.NewErrcode(data.Errcode.ConfigNotFound, fmt.Sprintf("没有PetAddInfos配置表，或的数据长度小于2"))
		return
	}
	fooT := tpl.(data.PetAddInfo)  // 一袋饲料的时间
	addExp = int64(expT.Val) * num // 饲料的经验

	now := utils.TNow().Unix()
	if pet.LiveEndTime < now {
		pet.LiveEndTime = now
	}
	foodTime := num * int64(fooT.Val)
	// 宠物吃了饲料，活跃时间不能超过24小时
	if (foodTime+pet.LiveEndTime)-now > 86400 {
		err = errors.NewErrcode(data.Errcode.ServerErr, fmt.Sprintf("宠物时间超过24小时, liveEndTime:%d", pet.LiveEndTime))
		return
	}
	// 宠物添加经验
	uProp, err = AddExp(pet, addExp)
	if err != nil {
		return
	}

	pet.LiveEndTime += foodTime
	uPet.FoodNum -= num
	uPet.Update(uPet)
	return
}

// 宠物增加经验
func AddExp(pet *m.Pet, num int64) (uProp *m.UpdateProp, err error) {
	petTpl, ok := data.Get("Pets", uint64(pet.Tid))
	if !ok {
		err = errors.NewErrcode(data.Errcode.ConfigNotFound, fmt.Sprintf("没有这个宠物配置tid:%d", pet.Tid))
		return
	}

	petT := petTpl.(data.Pet)
	if pet.Lv >= int64(petT.MaxLv) {
		return
	}
	// num *= data.PetExpNum
	uProp = m.NewUpdateProp()
	for {

		expTpl, ok := data.Get(petT.ExpTpl, uint64(pet.Lv))
		if !ok {
			err = errors.NewErrcode(data.Errcode.ConfigNotFound, fmt.Sprintf("没有这个宠物经验配置lv:%d", pet.Lv))
			return
		}
		expT := expTpl.(data.PetExp)
		if pet.Exp+num >= int64(expT.Exp) && pet.Lv < int64(petT.MaxLv) {
			pet.Lv++
			pSkillTpl, ok := data.Foreach(petT.SkillTpl, func(val interface{}) bool {
				val1 := val.(data.PetSkill)
				if int64(val1.Lv) == pet.Lv && int64(val1.Step) == pet.Step {
					return true
				}
				return false
			})
			if !ok {
				err = errors.NewErrcode(data.Errcode.ConfigNotFound, fmt.Sprintf("没有这个宠物技能模板：%s 配置 lv:%d, step:%d", petT.SkillTpl, pet.Lv, pet.Step))
				return nil, err
			}

			skillT := pSkillTpl.(data.PetSkill)

			uProp.Kvs = append(uProp.Kvs, &m.BaseKV{Key: data.GlobalEnum.Star, Val: int64(skillT.Star) - pet.Star})
			fmt.Println("宠物升级加星星 :", pet.Tid, "lv:", pet.Lv, "step:", pet.Step, int64(skillT.Star), " : ", pet.Star, " : ", utils.Obj2JsonStr(uProp.Kvs))
			pet.Star = int64(skillT.Star)
			fmt.Println("宠物升级加星星 end:", pet.Tid, "lv:", pet.Lv, "step:", pet.Step, int64(skillT.Star), " : ", pet.Star, " : ", utils.Obj2JsonStr(uProp.Kvs))
			num = pet.Exp + num - int64(expT.Exp)
			pet.SkillVal = pSkillTpl.(data.PetSkill).SkillVal
			pet.Exp = 0
			continue
		}
		pet.Exp += num
		break
	}
	return
}

// 获取玩家宠物个数
func CntPet(u *m.User) (r int64) {
	uPet := u.GetUserPet()
	r = 0
	for _, item := range uPet.Pets {
		if item.Status != 1 { // 没有激活不加
			continue
		}
		r += 1
	}
	return
}

// 计算宠物星星数量
func SumPetStar(u *m.User) (r int64) {
	uPet := u.GetUserPet()
	r = 0
	for _, item := range uPet.Pets {
		if item.Status != 1 { // 没有激活不加
			continue
		}
		r += item.Star
	}

	u.StarPet = r
	u.Update(u)
	return
}

// 用户宠物最大等级
func MaxPetLevel(u *m.User) (r int64) {
	uPet := u.GetUserPet()
	r = 0
	for _, item := range uPet.Pets {
		if item.Status != 1 { // 没有激活不加
			continue
		}
		if item.Lv > r {
			r = item.Lv
		}
	}
	return
}

// 统计不同宠物，相同等级数量，返回宠物等级
// func CntPetLevel(u *m.User) (r int64) {
// 	// 不同宠物，在限制等级以上，限制等级5、10、20、30、40
// 	uPet := u.GetUserPet()
// 	r = 0
// 	aLv := [5]int64{5, 10, 20, 30, 40}
// 	for _, lv := range aLv {
// 		// 满足等级宠物个数
// 		cnt := int64(0)
// 		// 遍历宠物
// 		for _, pet := range uPet.Pets {
// 			if pet.Status != 1 { // 没有激活不加
// 				continue
// 			}
// 			if pet.Lv >= lv { // 宠物等级大于等于限制等级，计数加一
// 				cnt++
// 			}
// 		}
// 		if cnt == 4 {
// 			r = lv
// 		}
// 	}
// 	return
// }

func ResetPet(us *m.User) {
	uPet := us.GetUserPet()
	pet, err := uPet.GetPet(uPet.SelectTid)
	if err != nil {
		return
	}
	pet.Exp = 0
	pet.Lv = 1
	pet.Step = 1
	pet.LiveEndTime = 0

	uPet.ExpNum = 0
	uPet.FoodNum = 0

	uPet.Update(uPet)
}
